parse-community / parse-server

Parse Server for Node.js / Express
https://parseplatform.org
Apache License 2.0
20.92k stars 4.78k forks source link

Parse Files saved hardcoded in json in array. #7123

Open uzaysan opened 3 years ago

uzaysan commented 3 years ago

New Issue Checklist

Issue Description

I have files in json. And I put that json inside of an array. But seems like parse files are saved hardcoded. Even we change fileAdapter, or baseUrl in file adapter, files return with the old url.

Steps to reproduce

Here is an example. This is How I save my files.

    for(var i = 0; i < mediaList.length; i++){
      //...other logic

      var mainmedia = new Parse.File(user.id, { base64: mediaData },mimeInfo.mime);
      var thumbfile = new Parse.File(user.id, { base64: thumbnail },mimeInfo.mime);

      var item = {"type":"image","width":ratiow,"height":ratioh,"media":mainmedia,"thumbnail":thumbfile};
      itemList.push(item);

    }
    post.set("media",itemList);

And baseUrl in my adapter is : http://files.example.com

Now file is saved with this url: http://files.example.com/filename

But If change baseUrl to this: http://my-new-file-endpoint.example.com I still get http://files.example.com/filename but I should get http://my-new-file-endpoint.example.com/filename

Actual Outcome

I get old url http://files.example.com/filename

Expected Outcome

I should get http://my-new-file-endpoint.example.com/filename

Failing Test Case / Pull Request

Environment

Server

Database

mtrezza commented 3 years ago

Thanks for reporting.

Now file is saved with this url: http://files.example.com/filename

If I understand correctly from your test case, you are manually creating a JavaScript object that looks similar to a Parse.File object with an absolute URL reference, but you are not actually instantiating a new Parse.File according to the docs, e.g.

const file = new Parse.File("myfile.txt", { base64: base64 });

A Parse File normally does not contain the absolute URL but only the filename. The file adapter only adds the base URL part when retrieving the file. Hence, the URL you are currently saving to the DB does not change when changing the baseUrl parameter.

uzaysan commented 3 years ago

If I understand correctly from your test case, you are saving a Parse File with a full URL to the database.

This is correct. Files are saved with url. And that url doesn't change after saving. File adapter is only used when we save object. And object keeps the first url they have got .

A Parse File normally does not contain the absolute URL but only the filename. The file adapter only adds the base URL part when retrieving the file.

This is how it should be. But in my database i can see the url

For example this is how it should be in database

media: filename

But i see this:

media: {
    __type:File,
    name: filename,
    url:fileUrl
}

İ created a pull request. İ wrote a test case. But in order to make test fail, we should change baseUrl after saving parse object (with files)

But i don't know how to do that. My pull request passes all test. Can you help there?

uzaysan commented 3 years ago

but you are not actually instantiating a new Parse.File according to the docs, e.g.

const file = new Parse.File("myfile.txt", { base64: base64 });

That's not true. See my example code in first message. İm creating a new file like this

var mainmedia = new Parse.File(user.id, { base64: mediaData },mimeInfo.mime);

But this shouldn't be the issue here

noaker commented 3 years ago

@uzaysan have you found the solution to this yet? I have experienced a similar problem

When I tag the created (and saved) ParseFile to my ParseObject and proceed to save the ParseObject, the ParseFile is saved as an Array type, rather than the File type.

Codes in Android Studio:

// Create and save file
ParseFile parseFile = new ParseFile("image.jpg", byteArray);
parseFile.saveInBackground();

// Tag file to ParseObject and save
ParseObject parseObject = new ParseObject("File");
parseObject.add("file", parseFile);
parseObject.add("user", ParseUser.getCurrentUser());
parseObject.saveInBackground();

The data type for "file" is File.

This is the error that I received: schema mismatch for File.file; expected File but got Array

After changing the data type to Array, this is the content of my "file" field in the database

[
  {
    "__type": "File",
    "name": "b8c7974254a3edbfe6b9075a63cf728b_image.jpg",
    "url": "https://linktomyimage"
  }
]

In addition to ParseFile, I also saved the user to the ParseObject. Strangely, the same happens to the data type for the user field - it becomes an array, rather than Pointer. Forcing it as a Pointer results in an error.

Note: The above issue only happens if I were to save the ParseObject (that contains the ParseFile) via the client Android app. Everything is working as it should if I were to use the File afterFileSave trigger in the cloud codes to create and save the ParseObject

uzaysan commented 3 years ago

When I tag the created (and saved) ParseFile to my ParseObject and proceed to save the ParseObject, the ParseFile is saved as an Array type, rather than the File type.

Your problem is different than mine. But its strange. I was also using android sdk and didnt face this issue. But I was passing android.File instead of byte array. What version of android sdk are you using? Can you try to pass file instead of byteArray?

Here is an example code:

// uri is the uri you get on activityResult call
File file = new File(uri.toString());
ParseFile parseFile = new ParseFile(file);
parseFile.saveInBackground(new SaveCallback() {
    @Override
    public void done(ParseException e) {
        ParseObject parseObject = new ParseObject("File");
        parseObject.add("file", parseFile);
        parseObject.add("user", ParseUser.getCurrentUser());
        parseObject.saveInBackground();                                                    
    }
});

//........