In function: _file_resource_create
Currently it has:
$dir = file_default_scheme() . '://';
// Build the destination folder tree if it doesn't already exists.
if (!file_prepare_directory($dir, FILE_CREATE_DIRECTORY)) {
return services_error(t("Could not create destination directory for file."), 500);
}

Then we cannot create directory for the file.

How about changing it to:
/*
$dir = file_default_scheme() . '://';
*/
$parts = pathinfo($file->filepath);
$dir = $parts['dirname'];
// Build the destination folder tree if it doesn't already exists.
if (!file_prepare_directory($dir, FILE_CREATE_DIRECTORY)) {
return services_error(t("Could not create destination directory for file."), 500);
}

Comments

marcingy’s picture

Category: bug » task

The better solution is for schema that is used by services to be configurable via a variable in my opinion so as public, private or some other stream wrapper and that a proper uri is provided so as mkdir implementation for the stream wrapper can do its thing. Moving this to a task.

ygerasimov’s picture

Status: Active » Needs review
StatusFileSize
new2.3 KB

@sf_wind do you need to change the wrapper, ie to be able to upload file to private:// or do you need to upload the file to specific file directory?

Here is attached patch that enables to upload to specific directory. You need to provide proper formed $item['filepath'] to accomplish that (see test).

kylebrowning’s picture

Status: Needs review » Needs work

This is an API change and cannot be committed in 3.x The only option is to provide an additional parameter to that adds this functional, such as an options array, with the value of $options['file path'] = 'whatever';

We can't just change that people MUST submit a file path with their objects, some might be relying on the fact that the API handles this for them.

wedge’s picture

Any chance of the patch in #2 going in? It's working fine for me with limited testing.

How is this an API change? I'm probably missing something but as far as I can tell, if filepath is not set, it works as before?

kylebrowning’s picture

needs to be

- $dir = file_default_scheme() . '://';
+ $dir = isset($file->filepath) ? drupal_dirname($file->filepath) : file_default_scheme() . '://';

wedge’s picture

Are you sure Kyle? A couple of lines above this line, filepath is set if it is not supplied when the file is created.
If I upload a file where filepath is not set, it gets set on line 166 (so $file->filepath equals "public://091.jpg")
$dir = drupal_dirname($file->filepath); with this input results in: $dir equals "public://" which I think is the expected result.

marcingy’s picture

I agree with Kyle as there are going to be cases when filepath has not been set according to the existing logic namelly when a filename is not provided - I do wonder if the first check should infact just be for the existence of a filepath because lower down we assume that we have a filename

$file->filemime = file_get_mimetype($file->filename);

Reroll to simplify the logic.

wedge’s picture

Perhaps this code should also check that filename is set then?

// If the file data is empty then bail
if (!isset($file->file)) {
  return FALSE;
}
marcingy’s picture

Status: Needs work » Needs review
StatusFileSize
new2.4 KB

Good idea reroll of patch with approach - also makes the failure throw a services error.

wedge’s picture

That's great, but missing one end parenthesis:

-if (!isset($file->file) || empty($file->filename) {
+if (!isset($file->file) || empty($file->filename)) {

Status: Needs review » Needs work

The last submitted patch, services-1325672-file-upload-specific-directory_0.patch, failed testing.

wedge’s picture

Status: Needs work » Needs review
StatusFileSize
new2.4 KB

Maybe this will work.

marcingy’s picture

Status: Needs review » Reviewed & tested by the community

Looks good and green bot!

7wonders’s picture

It works well for me but im not sure if its by design or not that if you have filename and filepath the filename is totally ignored. For example I am setting:

		params.put("uid", uid);
		params.put("filename", filename);
		params.put("filepath", "private://logs/");
		params.put("filesize", bytes);
		params.put("file", in);

Which ends up generating a random filename. Then doing it without filename like so:

		params.put("uid", uid);
		params.put("filepath", "private://logs/" + filename);
		params.put("filesize", bytes);
		params.put("file", in);

Works as intended.

7wonders’s picture

Actually, I was wrong. Missing the filename param out generates a 500 internal error. So strangely it requires a double use of filename to work as intended:

params.put("uid", uid);
params.put("filename", filename);
params.put("filepath", "private://logs/" + filename);
params.put("filesize", bytes);
params.put("file", in);
marcingy’s picture

Status: Reviewed & tested by the community » Fixed

Committed thanks.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.