web-dev-qa-db-ja.com

ファイルフィールドからファイル名とファイルパスを抽出するにはどうすればよいですか?

これが私が取り組んでいることです。コンテンツタイプのデフォルトのファイルフィールドアップロードウィジェットを介してZipファイルをアップロードできるようにしたいと思います。私はhook_node_presaveを使用してZipファイルを取得し、抽出はコアアップデートマネージャーに基づくヘルパー関数を使用しています。私が受け取っているエラーは:

通知:未定義のインデックス:filefield_unzip_node_presave()のファイル名(/sites/all/modules/filefield_unzip/filefield_unzip.moduleの18行目)。通知:未定義のインデックス:filefield_unzip_node_presave()内のuri(/sites/all/modules/filefield_unzip/filefield_unzip.moduleの19行目)。例外:アーカイバーはローカルファイルのみを操作できます:> archiver_get_archiver()ではサポートされていません(/ include /common.incの行8149)。

これが私のコードです:

/**
* @file

* Allows uploading and extracting a Zip file uploaded to a file field.
*/

/**
 * 
 * Implementation of hook_node_presave($node)
 * 
 */

function filefield_unzip_node_presave($node) {
if($node->type == 'game') {
    if (!empty($node->field_game_files)) {
        $zipFile = $node->field_game_files['und'][0]['filename'];
        $zipDirectory = $node->field_game_files['und'][0]['uri'];

        _filefield_unzip_archive_extract($zipFile, $zipDirectory);
    }
}
}

/**
 * 
 * Copy of the function used by the update manager update_manager_archive_extract($file, $directory)
 * 
 */

function _filefield_unzip_archive_extract($file, $directory) {
$archiver = archiver_get_archiver($file);
if (!$archiver) {
    throw new Exception(t('Cannot extract %file, not a valid archive.', array('%file' => $file)));
}

//Remove the directory if it exists, otherwise it might contain a mixture of old files mixed with new files (e.g. in cases where files
//were removed from a later release).
$files = $archiver->listContents();

//Unfortunately, we can only use the direct name to determine the project name. Some archivers list the first file as the directory (i.e., MODULE/)
//and others list an actual file (i.e., MODULE/README.TXT).
$project = strtok($files[0], '/\\');

$extract_location = $directory . '/' .$project;
if (file_exists($extract_location)) {
    file_unmanaged_delete_recursive($extract_location);
}

$archiver->extract($directory);
return $archiver;
}
2
Mike Conley

私はこれに対する解決策を見つけましたが、stackexchangeでは8時間回答を追加できません。すべて入力しましたので、戻ってアップロードするのを忘れた場合は、ここに投稿して回答をリクエストし、通知してください。

続ける...

1
DrupalDrop

完全なコードを確認できませんでしたが、以下のコードを変更して使用して、ファイルパスを取得できます。

$imgpath = file_load($ifid)->uri; print file_create_url($imgpath);

それが役に立てば幸い

1
Tushar

さて、さらに掘り下げた後、ようやく解決策を見つけました。

1)未定義のインデックスに関連する最初の2つのエラーについて...

ファイルオブジェクト全体が、hook_node_presaveにまだ読み込まれていないことがわかります。これがファイル名とURIが定義されていない理由です。この時点でオブジェクトに設定されていることを確認できるのは、データベースのfile_managedテーブルにあり、残りのメタデータを含む特定のフィールドテーブルを参照するファイルのfidだけです。ファイルをfidで取得し、全体をメタデータとともにスクリプトにロードする方法についての適切な説明は、次の場所にあります。 ファイルフィールドのファイルの変更(Drupal 7)

2)2番目の問題は、私の側の誤解でした。 archiver_get_archiver関数を使用するときは、$ fileパラメータのファイル名だけでなく、ファイルへの完全なパスを指定する必要があります(パスが$ directoryパラメータに含まれているという印象を受けました)。実際にファイルを解凍する場所に置き換えます。

更新されたコードについては、以下を参照してください:

<?php

/**
 * @file

 * Allows uploading and extracting a Zip file uploaded to a file field.
 */

/**
 * 
 * Implementation of hook_node_presave($node)
 * 
 */

function filefield_unzip_node_presave($node) {
    if($node->type == 'game') {
    //get fid from file_managed table in the DB
    $fid = $node->field_game_files[$node->language][0]['fid'];
    //load the file associated with this fid
    $file = file_load($fid);

    //get the full path to the file
    $zipFile = $file->uri;
    //remove the filename from the directory
    $zipDirectory = dirname($file->uri);

    if (!empty($node->field_game_files)) {
        _filefield_unzip_archive_extract($zipFile, $zipDirectory);
    }
}
}

/**
 * 
 * Copy of the function used by the update manager update_manager_archive_extract($file, $directory)
 * 
 */

function _filefield_unzip_archive_extract($file, $directory) {
$archiver = archiver_get_archiver($file);
if (!$archiver) {
    throw new Exception(t('Cannot extract %file, not a valid archive.', array('%file' => $file)));
}

//Remove the directory if it exists, otherwise it might contain a mixture of old files mixed with new files (e.g. in cases where files
//were removed from a later release).
$files = $archiver->listContents();

//Unfortunately, we can only use the direct name to determine the project name. Some archivers list the first file as the directory (i.e., MODULE/)
//and others list an actual file (i.e., MODULE/README.TXT).
$project = strtok($files[0], '/\\');

$extract_location = $directory . '/' .$project;
if (file_exists($extract_location)) {
    file_unmanaged_delete_recursive($extract_location);
}

$archiver->extract($directory);
return $archiver;
}
1
Mike Conley